﻿using DefCore.Core;
using DefCore.Interfaces;
using Ivory;
using Krypton;
using Krypton.Lights;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DefCore.AI.Pathing;

namespace DefCore.Actors
{
    public class Director
    {
        //Fields
        private List<Actor> _ActorList;

        //ctor
        public Director()
        {
            _ActorList = new List<Actor>();
        }

        //Methods
        public IEnumerable<Actor> GetAll()
        {
            return _ActorList;
        }
        public IEnumerable<Actor> FilterBy(Func<Actor, bool> func)
        {
            return this.GetAll().Where(func);
        }
        public IEnumerable<Actor> FilterByVisible()
        {
            //Calculate the Minimum tiles shown
            int minX, minY;
            minX = (int)(Objects.GameCamera.CameraTopLeft.X / Globals.TileSize.X);
            minY = (int)(Objects.GameCamera.CameraTopLeft.Y / Globals.TileSize.Y);
            minX = minX >= 1 ? minX - 1 : 0;
            minY = minY >= 1 ? minY - 1 : 0;

            //Calculate the Maximum Tiles shown
            int maxX, maxY;
            maxX = (int)((Objects.GameCamera.CameraTopLeft.X + Objects.GameCamera.CameraViewport.X) / Globals.TileSize.X);
            maxY = (int)((Objects.GameCamera.CameraTopLeft.Y + Objects.GameCamera.CameraViewport.Y) / Globals.TileSize.Y);
            maxX = maxX < Objects.LevelInstance.GameCellMap.MapWidth ? maxX + 1 : Objects.LevelInstance.GameCellMap.MapWidth;
            maxY = maxY < Objects.LevelInstance.GameCellMap.MapWidth ? maxY + 1 : Objects.LevelInstance.GameCellMap.MapHeight;

            Rectangle screen = new Rectangle(minX, minY, maxX, maxY);
            foreach(Actor a in this._ActorList)
            {
                if (screen.Intersects(a.HitBox))
                    yield return a;
            }
        }

        public IEnumerable<Light2D> GetLights()
        {
            foreach (Actor actor in FilterByVisible())
                if (actor.EntityLight != null)
                    yield return actor.EntityLight;
        }
        public IEnumerable<ShadowHull> GetHulls()
        {
            foreach (Actor actor in FilterByVisible())
                if (actor.EntityHull != null)
                    yield return actor.EntityHull;
        }

        public void AddActor(Actor actor)
        {
            actor.Create();
            _ActorList.Add(actor);
        }
        public void DeleteActor(Actor actor)
        {
            actor.Delete();
            _ActorList.Remove(actor);
        }
        
        public void Render(SpriteBatch batch, GameTime time)
        { 
            foreach (Actor actor in GetAll())
                actor.Render(batch, time);  
        }
        public void Solve(InputControl control, GameTime time)
        {
            foreach (Actor actor in GetAll())
                actor.Solve(control, time);
        }        
    }
}
